#region License

/* Copyright (C) 2007 Cristian Libardo
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

#endregion

using System.Collections;
using System.Collections.Generic;
using System.Web.UI;
using FlexiCommerce.Components;

namespace FlexiCommerce.Collections
{
    /// <summary>
    /// A generic item list.
    /// </summary>
    /// <typeparam name="T">The type of item to list.</typeparam>
    public class ItemList<T> : List<T>, IHierarchicalEnumerable where T : PersistenceItem
    {
        #region Constructors

        /// <summary>Initializes an empty instance of the ItemList class.</summary>
        public ItemList()
        {
        }

        /// <summary>Initializes an instance of the ItemList class with the supplied items.</summary>
        public ItemList(IEnumerable<T> items)
            : base(items)
        {
        }

        /// <summary>Initializes an instance of the ItemList class adding the items matching the supplied filter.</summary>
        /// <param name="items">The full enumeration of items to initialize with.</param>
        /// <param name="filters">The filters that should be applied to the full collection.</param>
        public ItemList(IEnumerable items, params ItemFilter[] filters)
        {
            AddRange(items, filters);
        }

        #endregion

        #region Methods

        public void AddRange(IEnumerable<T> items, params ItemFilter[] filters)
        {
            foreach (T item in items)
                if (AllMatch(item, filters))
                    Add(item);
        }

        public void AddRange(IEnumerable items, params ItemFilter[] filters)
        {
            foreach (T item in items)
                if (AllMatch(item, filters))
                    Add((T)item);
        }

        public void AddRange(IEnumerable<T> items, IEnumerable<ItemFilter> filters)
        {
            foreach (T item in items)
                if (AllMatch(item, filters))
                    Add(item);
        }

        private bool AllMatch(T item, IEnumerable<ItemFilter> filters)
        {
            foreach (ItemFilter filter in filters)
                if (!filter.Match(item))
                    return false;
            return true;
        }

        public void Sort(string sortExpression)
        {
            Sort(new ItemComparer<T>(sortExpression));
        }

        public bool ContainsAny(IEnumerable<T> items)
        {
            foreach (T item in items)
                if (Contains(item))
                    return true;
            return false;
        }

        /// <summary>Converts a list to a strongly typed list filtering all items of another type.</summary>
        /// <typeparam name="OtherT">The type the items in resulting list should have.</typeparam>
        /// <returns>A list of items of the correct type.</returns>
        public ItemList<OtherT> Cast<OtherT>() where OtherT : GenericPersistenceItem
        {
            return new ItemList<OtherT>(this, TypeFilter.Of<OtherT>());
        }
        #endregion

        #region IHierarchicalEnumerable Members

        public IHierarchyData GetHierarchyData(object enumeratedItem)
        {
            return new ItemHierarchyData((IHierarchicalPersistenceItem)enumeratedItem);
        }

        #endregion

        #region Nested type: ItemHierarchyData

        private class ItemHierarchyData : IHierarchyData
        {
            private IHierarchicalPersistenceItem item;

            public ItemHierarchyData(IHierarchicalPersistenceItem item)
            {
                this.item = item;
            }

            #region IHierarchyData Members

            IHierarchicalEnumerable IHierarchyData.GetChildren()
            {

                return item.Children.ToItemList<Category>(); ;
            }

            IHierarchyData IHierarchyData.GetParent()
            {
                return (item.Parent != null)
                        ? new ItemHierarchyData(item.Parent)
                        : null;
            }

            bool IHierarchyData.HasChildren
            {
                get { return item.Children.Count > 0; }
            }

            object IHierarchyData.Item
            {
                get { return item; }
            }

            string IHierarchyData.Path
            {
                get { return item.ID.ToString(); }
            }

            string IHierarchyData.Type
            {
                get { return item.GetType().Name; }
            }

            #endregion
        }

        #endregion
    }
}